#!/usr/bin/env guile
!#

(use-modules (charting) (charting csv) (ice-9 match))

(define data
  (match (program-arguments)
    ((_ csv-file)
     (csv-port->row-list (open-input-file csv-file)))
    ((prog . _)
     (format (current-error-port) "usage: ~a CSV-FILE\n" prog)
     (exit 1))))

(define (row->flags row)
  (let lp ((res 0) (i (1- (vector-length row))))
    (cond ((negative? i) res)
          ((string=? (vector-ref row i) "Y")
           (lp (logior (ash 1 i) res) (1- i)))
          (else (lp res (1- i))))))

;; partial schema
(define KNOWS-BZR 5)
(define KNOWS-GIT 6)
(define KNOWS-HG 7)
(define USES-BZR 8)
(define USES-GIT 9)
(define USES-HG 10)
(define FAVORITE 14)

(define (flag . flags)
  (apply logior (map (lambda (n) (ash 1 n)) flags)))

(define KNOWS-MASK (flag KNOWS-BZR KNOWS-GIT KNOWS-HG))
(define USES-MASK (flag USES-BZR USES-GIT USES-HG))

(define history
  `(("bzr" ,KNOWS-BZR ,USES-BZR)
    ("git" ,KNOWS-GIT ,USES-GIT)
    ("hg" ,KNOWS-HG ,USES-HG)))

(define (join set)
  (list (string-join (map car set) "+")
        (apply flag (map cadr set))
        (apply flag (map caddr set))))

(define (permute l)
  (cond ((null? l) '())
        ((null? (cdr l)) (list l))
        (else
         (let ((rest (permute (cdr l))))
           (append (cons (list (car l))
                         (map (lambda (x) (cons (car l) x)) rest))
                   rest)))))

(define permutations (map join (permute history)))

(define (fav=? what)
  (lambda (row) (string=? (vector-ref row FAVORITE) what)))

(define (row-has-flags row flags mask)
  (= (logand (row->flags row) mask) flags))

(define (fav->matches favs accessor mask prefix)
  (map (lambda (p)
         (list (length (filter (lambda (row)
                                 (row-has-flags row (accessor p) mask))
                               favs))
               (string-append prefix (car p))))
       permutations))

(define (do-favorite1 vcs)
  (cons vcs (fav->matches (filter (fav=? vcs) data) cadr KNOWS-MASK "familiar with ")))

(define (do-favorite2 vcs)
  (cons vcs (fav->matches (filter (fav=? vcs) data) caddr USES-MASK "regularly uses ")))

(define (dochart title data output)
  ((@ (charting draw) reset-colors!))
  (make-bar-chart title data
                  (map do-favorite1 '("bzr" "git" "hg" "svn"))
                  #:bar-width 15
                  #:group-spacing 25
                  #:max-y 240
                  #:chart-params '(#:x-axis-label "favorite vcs"
                                   #:y-axis-label "number of respondents")
                  #:ytick-label-formatter
                  (lambda (v) (format #f "~d" (inexact->exact (floor v))))
                  #:bar-value-formatter
                  (lambda (v) (format #f "~d" (inexact->exact (floor v))))
                  #:write-to-png output))

(dochart "version control systems: familiarity and preference" 
         (map do-favorite1 '("bzr" "git" "hg" "svn"))
         "favorite-by-known.png")

(dochart "version control systems: usage and preference" 
         (map do-favorite2 '("bzr" "git" "hg" "svn"))
         "favorite-by-used.png")
